-- fish.lua
-- this is where fish come from

fish = {
	kind = "prey", -- or "predator"
	pb = nil, -- sprite playback
	scale = 1, -- size of fish

	-- movement
	pos = vec2:new(),
	vel = vec2:new(),
	speed = 0, -- speed the fish is going
	ang = 0, -- angle fish is pointing
	set_ang = 0, -- the angle the fish wants to point
	ang_rate = 4, -- rate at which angle slews to desired angle, in radians per second
	decel = 0, -- rate at which fish slows while moving through water

	-- the fish's spawn point, which it uses to check if the coast is clear
	home = vec2:new(),

	-- radius at which it sees the octopus, also used to check if the coast is clear
	detectionRadius = 800,

	-- timer for how long the octopus is sighted before fish becomes alerted/normal
	stateCounter = 0,
	sightedTimerLimit = .4, --amount of time for fish to think octo isnt there
	heMustBeGone = 1, --amount of time for fish to think octo isnt nearby
	justAttackedTimeLimit = .8, --amount of time for fish to let octo escape and not hurt again
	-- finite state machine
--	state = 
--	{
--		"normal",          -- moves towards nearest waypoint/home
--		"sighted",         --stops movement
--		"alerted",
--		"justAttacked",  --this is the animation where attacking takes place because enemy will be attacking dismembered arm
--	},

	-- current state
	currstate = "normal",

	-- table of vec2's for patrol route
	waypoints = {},

	-- current waypoint that the fish is heading toward
	currwaypoint = 1,

	-- proxiimity from a waypoint at which it is considered to be reached
	waypointDistance = 500,
}

function fish:new(o)
	o = o or {}
	setmetatable(o, self)
	self.__index = self
	return o
end


function fish:init( pkind, start_x, start_y )
	local r = fish:new()
	
	r.pos = vec2:init(start_x, start_y)
	r.home = vec2:init(start_x, start_y)
	
	table.insert(r.waypoints, r.home)
	
	r.kind = pkind
	r.currstate = "normal"
	
	-- type-specific initialization
	if r.kind == "prey" then
		if math.random() < 0.5 then
			r.pb = playback:init(sprite_table["Fish_02"], 1/20)
		else
			r.pb = playback:init(sprite_table["Fish_03"], 1/20)
		end
	elseif r.kind == "shark" then
		r.pb = playback:init(sprite_table["Shark_01"], 1/30)
		r.scale = 2.5
		r.ang_rate = 1
	elseif r.kind == "crab" then
		if math.random() < 0.5 then
			r.pb = playback:init(sprite_table["Lobster_01"], 1)
			r.scale = 0.9
		else
			r.pb = playback:init(sprite_table["Crab_01"], 1)
			r.scale = 0.5
		end
	else
		r.pb = nil
	end
	
	return r
end

function fish:doesPatrol()
	return #self.waypoints > 0
end

function fish:pickWaypoint()
	local wdist
	local bdist = math.HUGE
	local bway = nil
	
	for i, v in ipairs(self.waypoints) do
		wdist = dist(v, self.pos)
		
		if wdist < bdist then
			bdist = wdist
			bway = i
		end
	end
	
	self.currwaypoint = bway
end

function fish:patrol()
	-- did we hit a waypoint?
	if dist(self.waypoints[self.currwaypoint], self.pos) < self.waypointDistance then
		self.currwaypoint = self.currwaypoint + 1
		if self.currwaypoint == #self.waypoints then
			self.currwaypoint = 1
		end
	end
	
	self.set_ang = (self.waypoints[self.currwaypoint] - self.pos).ang()
end

function fish:update(dt)
   local octodiff = octopus:getPos() - self.pos
	local octoang = octodiff:ang()
	local octodist = octodiff:len()
	
--	bug = self.currstate

	self.stateCounter = self.stateCounter + dt

	if self.currstate == "justAttacked" then
		if self.stateCounter > self.justAttackedTimeLimit then
				self.currstate = "sighted"
				self.stateCounter = 0
		end
		
	-- if colliding with octopus (might change when michael gets physics collision up and running)
	else if octodist < 60 then
		if self.kind == "prey" then --may have to check if octo is invisible as well if we dont want octo to eat while invisible
				--I die, (octopus enters eat state?), fishPoint++
				-- SOUND
		--		love.audio.play(audio.eats[1])
		
				octopus:addScore(1000)
				
				self.todelete = true -- die a horrible death

		elseif self.kind == "shinyPrey" then --may have to check if octo is invisible as well if we dont want octo to eat while invisible
				--I die, (octopus enters eat state?), fishPoint++, camoBar++
				-- add to camo bar
				-- SOUND
	--			love.audio.play(audio.eats[1])
				self.todelete = true -- die a horrible death

		elseif self.kind == "crab" then
			if self.currstate == "alerted" then
				octopus:damage() -- hit the octopus
			   --I do not keep attacking octopus
			   self.currstate = "justAttacked"
			   self.stateCounter = 0
			else
				--I die, (octopus enters eat state?) fishPoint++
				-- SOUND
		--		love.audio.play(audio.eats[2])
				octopus:addScore(1000)
				self.todelete = true -- die a horrible death
			end

		elseif self.kind == "shinyCrab" then
			if self.currstate == "alerted" then
				octopus:damage() -- hit the octopus
			   --I do not keep attacking octopus
			   self.currstate = "justAttacked"
			   self.stateCounter = 0
			else 
				--I die, (octopus enters eat state?) fishPoint++
				-- add to camo bar
				-- SOUND
		--		love.audio.play(audio.eats[2])
				self.todelete = true -- die a horrible death
			end

		elseif self.kind == "shark" then
			if self.currstate == "alerted" or not octopus.invisible then
			   --Octopus loses limb
			   --I do not keep attacking octopus
				octopus:damage() -- hit the octopus
				-- SOUND
			--	love.audio.play(audio.shark_bite)
			   self.currstate = "justAttacked"
			   self.stateCounter = 0
			end
		end

	-- NORMAL state behavior
	elseif self.currstate == "normal" then
	
		if self.stateCounter > 1 then
			local dhome = self.home - self.pos
			if dhome:len() > 500 then -- go home if too far away
				self.set_ang = dhome:ang()
				self.speed = 200
			else -- otherwise randomly change direction every so often
				self.speed = 200
				self.set_ang = self.set_ang + math.random(-2, 2)
			end
			
			self.stateCounter = 0
		end

		if octodist <= self.detectionRadius and not octopus.invisible then
			self.currstate = "sighted"
			self.stateCounter = 0
			
			if self.kind == "prey" then
				-- SOUND
		--		love.audio.play(audio.fish_sighted)
			
			elseif self.kind == "shinyPrey" then
				-- SOUND
		--		love.audio.play(audio.fish_sighted)
			end
			
		else
		-- TODO: patrol. Go to the nearest waypoint. OR randomly mill around
		end

	-- SIGHTED state behavior
	elseif self.currstate == "sighted" then

		-- TODO: stop moving
		-- TODO: look at the octopus
		
		self.speed = 0
		self.ang = octoang
		self.set_ang = self.ang -- turn instantly

		if self.stateCounter > self.sightedTimerLimit then

			-- if the octopus is still sighted, go into alert! oh noes!
			if octodist <= self.detectionRadius and not octopus.invisible then
				self.currstate = "alerted"
				self.stateCounter = 0
				
				if self.kind == "crab" then
					-- SOUND
			--		love.audio.play(audio.crustacean_alert)
				
				elseif self.kind == "shinyCrab" then
					-- SOUND
			--		love.audio.play(audio.crustacean_alert)
				
				elseif self.kind == "shark" then
					-- SOUND
			--		love.audio.play(audio.shark_alert)
				end
				
			-- otherwise, be chill
			else
				self.currstate = "normal"
				self.stateCounter = 0
			end
		end

	-- ALERTED state behavior
	elseif self.currstate == "alerted" then

		-- TODO: based on type, either pursue or flee
		if self.kind == "prey" then
		
			self.ang = octoang + math.pi
			self.set_ang = self.ang -- turn around instantly
			self.speed = 2000 -- RUN AWAY!!!
			
			if octodist <= self.detectionRadius and not octopus.invisible then
			-- TODO: get vector from the octopus to self and give a burst of speed in the opposite direction
			-- i.e. run away
				self.stateCounter = 0

			-- This checks if the fish is convinced The octopus is gone
			elseif self.stateCounter > self.heMustBeGone then
				self.currstate = "sighted" --Go to Sighted state
				self.stateCounter = 0
				
			else
				--Continue on present course
			end
			
--		elseif self.kind =="shinyPrey"
--		
--			if getCamera():isVisible(self.pos) then
--				--get vector from the octopus to self and give a burst of speed in the opposite direction
--			else if --[[ If octopus isnt in camera distance of my home--]]then
--				--magically go home
--				self.stateCounter = 0
--				self.currstate = self.state.normal				
--			else
--				--disappear from area, maybe set coordinates to off world or inaccessible area
--			end
		
		elseif self.kind == "crab" then
			
			if octodist <= self.detectionRadius and not octopus.invisible then
			-- TODO: get vector from the octopus to self and give a burst of speed in that direction
				self.stateCounter = 0

			-- This checks if the fish is convinced The octopus is gone
			elseif self.stateCounter > self.heMustBeGone then
				self.currstate = "sighted" --Go to Sighted state
				self.stateCounter = 0
				
			else
				--Continue on present course
			end

--		elseif self.kind =="shinyCrab"
--		
--			if --[[If I am in view of the camera --]]then
--				--get vector from the octopus to self and give a burst of speed in that  direction
--			else if --[[ If octopus isnt in camera distance of my home--]]then
--				--magically go home
--				self.stateCounter = 0
--				self.currstate = self.state.normal		
--			else
--				--disappear from area, maybe set coordinates to off world or inaccessible area
--			end
		
		elseif self.kind == "shark" then
			if octodist <= self.detectionRadius and not octopus.invisible then
			-- TODO: get vector from the octopus to self and give a burst of speed in the that direction
				self.stateCounter = 0

			-- This checks if the fish is convinced The octopus is gone
			elseif self.stateCounter > self.heMustBeGone then
				self.currstate = "sighted" --Go to Sighted state
				self.stateCounter = 0
				
			else
				--Continue on present course
			end		
		
		end
	end
	end
	-- end of state logic
	
	
	-- now on to motion

 	-- handle slewing towards desired angle
	local d = ang_diff(self.set_ang, self.ang)
	local da = dt * self.ang_rate
	if math.abs(d) < da then
            self.ang = self.set_ang
	elseif d < 0 then
            self.ang = self.ang - da
	else --if d > 0 then
            self.ang = self.ang + da
	end
	
	self.ang = ang_norm(self.ang) -- normalize your angle!!!
	
	-- handle speed computation
	self.speed = self.speed - (self.speed * dt * self.decel)
	self.vel = self.speed * vec2:dir(self.ang)
	
	-- physics update
	self.pos = self.pos + dt * self.vel

	-- sprite update
	self.pb:update(dt)

end

function fish:draw()
	love.graphics.setColor(255, 255, 255)
	self.pb:draw(self.pos, self.ang, self.scale)
end













